﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Barebones.Components;
using Barebones.Structure;
using Barebones.Dependencies;
using Barebones.Communication;
using Barebones.Communication.Messages;

namespace Barebones.Framework
{
    public class Engine
    {
        LogicContainer m_Components = new LogicContainer();
        List<Entity> m_Entities = new List<Entity>();
        Forum m_Forum = new Forum();

        public Forum Forum
        { get { return m_Forum; } }

        public Engine()
        {
            m_Forum.RegisterListener<ComponentAddedMessage>(message => 
                {
                    m_Components.Link(message.Component);
                });

            m_Forum.RegisterListener<ComponentRemovedMessage>(message =>
                {
                    m_Components.UnLink(message.Component);
                });
        }

        public T GetComponent<T>() where T : class, IDependent
        {
            return m_Components.Get<T>();
        }

        public void AddComponent(EngineComponent item)
        {
            item.SetOwner(this);
            m_Components.Add(item);
        }

        public void RemoveComponent(EngineComponent item)
        {
            m_Components.Remove(item);
            item.SetOwner(null);
        }

        public void Update(float dt)
        {
            m_Forum.Fire<PreUpdateMessage>(new PreUpdateMessage());

            m_Components.Update(dt);

            m_Entities.ForReversed(item => item.Update(dt));

            m_Forum.Fire<PostUpdateMessage>(new PostUpdateMessage());
        }

        public void Draw()
        {
            m_Forum.Fire<PreRenderMessage>(new PreRenderMessage());

            m_Entities.ForReversed(item => item.Draw());

            m_Components.Draw();

            m_Forum.Fire<PostRenderMessage>(new PostRenderMessage());
        }

        public Entity CreateEntity()
        {
            Entity creation = new Entity(this);
            m_Entities.Insert(0, creation);
            return creation;
        }

        internal void DestroyEntity(Entity ent)
        {
            m_Entities.Remove(ent);
        }
    }
}
